/////////////////////////////////////////////////////////////////////////
//
// Amuse Engine - graphics
// Copyright (c) 2014.  All Rights Reserved
//
// File:		AERenderNode.h
// Author:		Gianluca Belardelli
// Date:		10/06/2014
//
/////////////////////////////////////////////////////////////////////////
#ifndef _AERENDERNODE_H_
#define _AERENDERNODE_H_

class AERenderNode : public AERenderContextContainer
{
// Members
protected:
	AERenderContext	*m_lpFinalTargetContext;

	AEFLOAT32 		m_fPixelAspectRatio;

	AEINT32 		m_nUpdateCounter;

	AEBOOL32 		m_bRenderingEnabled;
	AEBOOL32 		m_bIsInitialized;

	/// \brief
	///   Flag which signifies whether the renderer properties have changed inside a PropertyUpdate block.
	AEBOOL32 		m_bUpdateDirty;

// Methods
public:
	/// \brief Constructor of the renderer node.
	/// Creates a new renderer node. Renderer nodes will have to be registered using VisRenderer_cl::SetRendererNode();
	/// otherwise, they will not be taken into account by the engine.
	/// \param pTargetContext
	///   The target render context of the renderer node. This can be the main render context (if you want the renderer
	///   node to output to the backbuffer), or some intermediate render context. Unless the renderer node explicitly
	///   supports it, renderer node implementations assume that their viewport covers the whole target context.
	AE_DLLIMPEXP AERenderNode( AERenderContext *lpTargetContext = 0L );

	/// \brief Virtual destructor of the renderer node.
	AE_DLLIMPEXP virtual ~AERenderNode( void );

	/// \brief Sets this as the current renderer node, triggers switching callbacks, and performs visibility determination and rendering.
	AE_DLLIMPEXP virtual void Execute( void );

	/// \brief Overridden base function.
	/// Recreates the renderer node after setting the variable, unless called inside a Begin/EndPropertyUpdate block.
	/// \param name The name of the variable to update.
	/// \param value A value string that represents the new variable value.
	AE_DLLIMPEXP virtual AEBOOL32 SetVariable( const char *lpName, const char *lpValue );

	/// \brief Tells the renderer node that multiple properties will be updated inside a BeginPropertyUpdate/EndPropertyUpdate pair.
	/// A BeginPropertyUpdate/EndPropertyUpdate bracket can be used to avoid unnecessary memory allocations and
	/// reduce resource recreation when updating multiple renderer node properties in a row.
	AE_DLLIMPEXP virtual void BeginPropertyUpdate( void );

	/// \brief Ends the property update initiated by a call to BeginPropertyUpdate.
	/// By default, ReInitializeRenderer is called by this method if any properties have been changed inside the update block.
	AE_DLLIMPEXP virtual void EndPropertyUpdate( void );

	/// \brief Returns the reference context for this renderer node.
	/// The "reference context" for a renderer node is the render context to which the opaque scene geometry gets
	/// rendered. For deferred rendering, this is the initial g-buffer render context, for forward rendering, this is
	/// the offscreen render target. Initial FOV information and clip planes may be taken from this context, and
	/// rendering effects may choose to use Render Hooks to render into this context.
	/// \returns  A pointer to the reference context for opaque geometry rendering.
	AE_DLLIMPEXP virtual AERenderContext *GetReferenceContext( void ) { return 0L; }

	/// \brief Returns the translucency reference context for this renderer node.
	/// The "translucency reference context" for a renderer node is the render context to which the translucent scene geometry gets
	/// rendered. For deferred rendering, this is the translucency render context, for forward rendering, this is
	/// typically the same offscreen render target that gets used for opaque geometry. Initial FOV information and clip planes may
	/// be taken from this context, and rendering effects may choose to use Render Hooks to render into this context.
	/// \returns A pointer to the reference context for translucent geometry rendering.
	AE_DLLIMPEXP virtual AERenderContext *GetTranslucencyReferenceContext( void ) { return 0L; }

	/// \brief Returns the target context for this renderer node.
	/// The target render context for a renderer node is specified as a parameter to the constructor.
	/// \returns A pointer to the target context.
	AE_DLLIMPEXP virtual AERenderContext *GetFinalTargetContext( void ) { return m_lpFinalTargetContext; }

	/// \brief Sets the final target context for this renderer node.
	/// You must explicitly deinitialize the renderer node before calling this method, and initialize the renderer node
	/// afterwards.
	/// The target render context for a renderer node is set to the passed target context. If the target context
	/// has a visibility collector, it will be used for all contexts that require one. This may set the render context's
	/// property of being the reference context for the visibility collector.
	/// Implementations of this class should also make sure to forward properties such as cull mode settings and filter mask
	/// from the final target context to all relevant internal contexts.
	/// \param pNewContext A pointer to the target context that should be used as the new final target context.
	AE_DLLIMPEXP virtual void SetFinalTargetContext( AERenderContext *lpNewContext ) {}

	/// \brief  Called when the renderer node is activated.
	/// Renderer nodes can be activated and deactivated. Applications can call OnActivate to tell the renderer
	/// node that it should start updating again after it has been disabled using OnDeactivate(). After a call to
	/// OnActivate, the renderer node has to be in a state where it is fully usable (of course, if this was already
	/// the case prior to the call to OnActivate, the method does not have to do anything).
	AE_DLLIMPEXP virtual void OnActivate( void ) {}

	/// \brief Called when the renderer node is deactivated.
	/// Renderer nodes can be activated and deactivated. Applications can call OnDeactivate to tell the renderer
	/// node that it should stop updating itself until OnActivate() is called. Implementations may choose to free up
	/// memory and de-initialize the renderer node.
	AE_DLLIMPEXP virtual void OnDeactivate( void ) {}

	/// \brief Called to initialize the renderer.
	AE_DLLIMPEXP virtual void InitializeRenderer( void );

	/// \brief Called to de-initialize the renderer.
	AE_DLLIMPEXP virtual void DeInitializeRenderer( void );

	/// \brief Called to de-initialize and then initialize the renderer
	AE_DLLIMPEXP virtual void ReInitializeRenderer( void );

	/// \brief Enabled/disables rendering of this renderer node. Lightweight function, use this if you frequently switch between
	///   renderer nodes without intending to de-initialize them.
	AE_DLLIMPEXP virtual void SetRenderingEnabled( AEBOOL32 bStatus );

	/// \brief Returns whether rendering of this renderer node is currently enabled.
	inline AEBOOL32 GetRenderingEnabled( void ) const { return m_bRenderingEnabled; }

	/// \brief Returns whether the renderer node is initialized (ie. has created its contexts and resources)
	inline AEBOOL32 IsInitialized( void ) const { return m_bIsInitialized; }
};

#endif // _AERENDERNODE_H_

